package com.example.cinemasystemv2.service;

import com.example.cinemasystemv2.entity.Movie;
import com.example.cinemasystemv2.entity.Screening;
import com.example.cinemasystemv2.entity.ScreeningRoom;
import com.example.cinemasystemv2.repository.ScreeningRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class ScreeningService {
    
    @Autowired
    private ScreeningRepository screeningRepository;
    
    @Autowired
    private SystemLogService systemLogService;
    
    @Autowired
    private MovieService movieService;
    
    @Autowired
    private ScreeningRoomService screeningRoomService;
    
    public List<Screening> getAllScreenings() {
        return screeningRepository.findAll();
    }
    
    public Optional<Screening> getScreeningById(Long id) {
        return screeningRepository.findByIdWithAssociations(id);
    }
    
    public List<Screening> getScreeningsByMovie(Movie movie) {
        return screeningRepository.findByMovie(movie);
    }
    
    public List<Screening> getScreeningsByMovieAndDate(Movie movie, LocalDateTime date) {
        if (date == null) {
            return getScreeningsByMovie(movie);
        }
        // 获取指定日期的开始和结束时间
        LocalDateTime startOfDay = date.withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = date.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
        
        return screeningRepository.findByMovieAndDateRange(movie, startOfDay, endOfDay);
    }
    
    public List<Screening> getScreeningsByRoom(ScreeningRoom room) {
        return screeningRepository.findByRoom(room);
    }
    
    public List<Screening> getScreeningsByDate(LocalDateTime date) {
        return screeningRepository.findByDate(date);
    }
    
    public List<Screening> getScreeningsByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
        return screeningRepository.findByDateRange(startTime, endTime);
    }
    
    public List<Screening> getUpcomingScreenings() {
        LocalDateTime startOfToday = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime endOfWeek = startOfToday.plusWeeks(1).minusSeconds(1);
        return screeningRepository.findByDateRange(startOfToday, endOfWeek);
    }
    
    public List<Screening> getTodayScreenings() {
        LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);
        return screeningRepository.findByDateRange(startOfDay, endOfDay);
    }
    
    public List<Screening> getNext3DaysScreenings() {
        LocalDateTime startOfToday = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime endOf3Days = startOfToday.plusDays(3).minusSeconds(1);
        return screeningRepository.findByDateRange(startOfToday, endOf3Days);
    }
    
    public List<Screening> getScreeningsByMovieId(Long movieId) {
        Optional<Movie> movieOpt = movieService.getMovieById(movieId);
        if (movieOpt.isPresent()) {
            return screeningRepository.findByMovie(movieOpt.get());
        }
        return new ArrayList<>();
    }
    
    public List<Screening> searchScreenings(String keyword) {
        return screeningRepository.searchScreenings(keyword);
    }
    
    public Screening saveScreening(Screening screening) {
        // 检查时间冲突
        if (hasTimeConflict(screening)) {
            throw new IllegalArgumentException("该时间段放映厅已被占用");
        }
        
        // 如果是新场次（ID为null），分配最小可用ID
        if (screening.getId() == null) {
            screening.setId(findNextAvailableId());
        }
        
        Screening savedScreening = screeningRepository.save(screening);
        systemLogService.log("场次保存: " + screening.getMovie().getTitle() + " - " + screening.getRoom().getName(), 
                           "system", "SAVE_SCREENING");
        return savedScreening;
    }
    
    private Long findNextAvailableId() {
        List<Long> existingIds = screeningRepository.findAllIds();
        if (existingIds.isEmpty()) {
            return 1L;
        }
        
        // 查找最小的可用ID
        Long nextId = 1L;
        for (Long id : existingIds) {
            if (id.equals(nextId)) {
                nextId++;
            } else {
                break;
            }
        }
        return nextId;
    }
    
    public Screening createScreening(Movie movie, ScreeningRoom room, LocalDateTime startTime, double price) {
        Screening screening = new Screening(movie, room, startTime, price);
        return saveScreening(screening);
    }
    
    public Screening updateScreening(Screening screening) {
        // 检查时间冲突（排除自身）
        if (hasTimeConflictExcludingSelf(screening)) {
            throw new IllegalArgumentException("该时间段放映厅已被占用");
        }
        
        Screening updatedScreening = screeningRepository.save(screening);
        systemLogService.log("场次更新: " + screening.getMovie().getTitle() + " - " + screening.getRoom().getName(), 
                           "system", "UPDATE_SCREENING");
        return updatedScreening;
    }
    
    public void deleteScreening(Long id) {
        Optional<Screening> screeningOpt = screeningRepository.findByIdWithAssociations(id);
        if (screeningOpt.isPresent()) {
            Screening screening = screeningOpt.get();
            // 在删除之前先获取需要的信息，避免懒加载问题
            String movieTitle = screening.getMovie().getTitle();
            String roomName = screening.getRoom().getName();
            
            screeningRepository.deleteById(id);
            systemLogService.log("场次删除: " + movieTitle + " - " + roomName, 
                               "system", "DELETE_SCREENING");
        }
    }
    
    public boolean hasTimeConflict(Screening screening) {
        LocalDateTime newStartTime = screening.getStartTime();
        LocalDateTime newEndTime = newStartTime.plusMinutes(screening.getMovie().getDuration());
        
        // 添加15分钟的缓冲时间（清场和准备时间）
        final int BUFFER_MINUTES = 15;
        LocalDateTime newStartTimeWithBuffer = newStartTime.minusMinutes(BUFFER_MINUTES);
        LocalDateTime newEndTimeWithBuffer = newEndTime.plusMinutes(BUFFER_MINUTES);
        
        // 获取同一放映厅的所有场次
        List<Screening> roomScreenings = screeningRepository.findByRoom(screening.getRoom());
        
        // 检查时间冲突：考虑缓冲时间的重叠检查
        // 新场次（含缓冲）开始时间 < 现有场次结束时间 AND 新场次（含缓冲）结束时间 > 现有场次开始时间
        for (Screening existingScreening : roomScreenings) {
            LocalDateTime existingStartTime = existingScreening.getStartTime();
            LocalDateTime existingEndTime = existingStartTime.plusMinutes(existingScreening.getMovie().getDuration());
            
            if (newStartTimeWithBuffer.isBefore(existingEndTime) && newEndTimeWithBuffer.isAfter(existingStartTime)) {
                return true;
            }
        }
        
        return false;
    }
    
    public boolean hasTimeConflictExcludingSelf(Screening screening) {
        LocalDateTime newStartTime = screening.getStartTime();
        LocalDateTime newEndTime = newStartTime.plusMinutes(screening.getMovie().getDuration());
        
        // 添加15分钟的缓冲时间（清场和准备时间）
        final int BUFFER_MINUTES = 15;
        LocalDateTime newStartTimeWithBuffer = newStartTime.minusMinutes(BUFFER_MINUTES);
        LocalDateTime newEndTimeWithBuffer = newEndTime.plusMinutes(BUFFER_MINUTES);
        
        // 获取同一放映厅的所有场次
        List<Screening> roomScreenings = screeningRepository.findByRoom(screening.getRoom());
        
        // 检查时间冲突：考虑缓冲时间的重叠检查
        // 新场次（含缓冲）开始时间 < 现有场次结束时间 AND 新场次（含缓冲）结束时间 > 现有场次开始时间
        for (Screening existingScreening : roomScreenings) {
            // 排除自身
            if (screening.getId() != null && screening.getId().equals(existingScreening.getId())) {
                continue;
            }
            
            LocalDateTime existingStartTime = existingScreening.getStartTime();
            LocalDateTime existingEndTime = existingStartTime.plusMinutes(existingScreening.getMovie().getDuration());
            
            if (newStartTimeWithBuffer.isBefore(existingEndTime) && newEndTimeWithBuffer.isAfter(existingStartTime)) {
                return true;
            }
        }
        
        return false;
    }
    
    public List<Screening> getAvailableScreenings() {
        return getUpcomingScreenings();
    }
    
    // 自动排片方法
    public int autoScheduleScreenings() {
        int scheduledCount = 0;
        
        try {
            // 获取所有正在上映的电影
            List<Movie> movies = movieService.getAllMovies().stream()
                .filter(movie -> movie.getStatus().equals("正在上映"))
                .collect(java.util.stream.Collectors.toList());
            
            // 获取所有放映厅
            List<ScreeningRoom> rooms = screeningRoomService.getAllRooms();
            
            if (movies.isEmpty() || rooms.isEmpty()) {
                return 0;
            }
            
            // 为未来3天自动安排场次
            LocalDateTime startDate = LocalDateTime.now().plusDays(1).toLocalDate().atTime(9, 0); // 从明天9点开始
            
            for (int day = 0; day < 3; day++) {
                LocalDateTime currentDate = startDate.plusDays(day);
                
                for (ScreeningRoom room : rooms) {
                    // 从每天9点开始为每个放映厅安排场次
                    LocalDateTime currentTime = currentDate.withHour(9).withMinute(0);
                    LocalDateTime endOfDay = currentDate.withHour(22).withMinute(0);
                    
                    while (currentTime.isBefore(endOfDay)) {
                        // 随机选择一部电影
                        Movie selectedMovie = movies.get((int) (Math.random() * movies.size()));
                        
                        // 创建场次
                        Screening screening = new Screening();
                        screening.setMovie(selectedMovie);
                        screening.setRoom(room);
                        screening.setStartTime(currentTime);
                        
                        // 检查该时间段是否已有安排
                        if (!hasTimeConflict(screening)) {
                            
                            // 根据时间段设置价格
                            double price = 35.0; // 基础价格
                            int hour = currentTime.getHour();
                            if (hour >= 18 && hour <= 21) {
                                price = 45.0; // 黄金时段
                            } else if (hour >= 14 && hour <= 17) {
                                price = 40.0; // 下午时段
                            }
                            
                            screening.setPrice(price);
                            
                            try {
                                screeningRepository.save(screening);
                                scheduledCount++;
                                
                                systemLogService.log("自动排片: " + selectedMovie.getTitle() + " - " + 
                                    room.getName() + " - " + currentTime.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), 
                                    "system", "AUTO_SCHEDULE");
                                
                                // 计算下一个可用时间：电影时长 + 15分钟缓冲时间
                                currentTime = currentTime.plusMinutes(selectedMovie.getDuration() + 15);
                            } catch (Exception e) {
                                // 如果保存失败，尝试下一个时间段（30分钟后）
                                currentTime = currentTime.plusMinutes(30);
                            }
                        } else {
                            // 如果有冲突，尝试30分钟后的时间段
                            currentTime = currentTime.plusMinutes(30);
                        }
                     }
                 }
            }
        } catch (Exception e) {
            systemLogService.log("自动排片失败: " + e.getMessage(), "system", "AUTO_SCHEDULE_ERROR");
            throw new RuntimeException("自动排片失败: " + e.getMessage());
        }
        
        return scheduledCount;
    }
}